from functools import wraps
from flask import request
from flask_jwt_extended import verify_jwt_in_request, get_jwt_identity, get_jwt
from app.models.admin import Admin
from app.models.user import User


def token_required(f):
    """JWT令牌验证装饰器 - 兼容Flask-RESTX"""
    @wraps(f)
    def decorated(*args, **kwargs):
        try:
            # 验证JWT令牌
            verify_jwt_in_request()
            current_admin_id_str = get_jwt_identity()
            
            # 检查管理员ID是否存在
            if not current_admin_id_str:
                return {'code': 401, 'message': '令牌中缺少用户身份信息', 'data': None}, 401
            
            # 将字符串ID转换为整数
            try:
                current_admin_id = int(current_admin_id_str)
            except (ValueError, TypeError):
                return {'code': 401, 'message': '令牌中的用户ID格式无效', 'data': None}, 401
            
            # 获取当前管理员信息
            current_admin = Admin.query.get(current_admin_id)
            if not current_admin:
                return {'code': 401, 'message': '管理员不存在', 'data': None}, 401
            
            if not current_admin.status:
                return {'code': 401, 'message': '管理员已被禁用', 'data': None}, 401
            
            # 将current_admin注入到kwargs中
            kwargs['current_admin'] = current_admin
            return f(*args, **kwargs)
            
        except Exception as e:
            # 记录具体错误信息用于调试
            print(f"JWT验证错误: {str(e)}")
            error_msg = str(e)
            if 'expired' in error_msg.lower():
                return {'code': 401, 'message': 'Token已过期', 'data': None}, 401
            elif 'invalid' in error_msg.lower():
                return {'code': 401, 'message': 'Token格式无效', 'data': None}, 401
            elif 'signature' in error_msg.lower():
                return {'code': 401, 'message': 'Token签名验证失败', 'data': None}, 401
            else:
                return {'code': 401, 'message': f'认证失败: {error_msg}', 'data': None}, 401
    
    return decorated


# 为了保持兼容性，添加admin_required别名
admin_required = token_required


def check_permission(permission):
    """权限检查装饰器"""
    def decorator(f):
        @wraps(f)
        def decorated(current_admin, *args, **kwargs):
            # 这里可以实现具体的权限检查逻辑
            # 暂时先简单返回，后续可以扩展
            return f(current_admin, *args, **kwargs)
        return decorated
    return decorator


def user_token_required(f):
    """用户JWT令牌验证装饰器 - 与管理员令牌分离"""
    @wraps(f)
    def decorated(*args, **kwargs):
        try:
            # 验证JWT令牌
            verify_jwt_in_request()
            jwt_identity = get_jwt_identity()
            
            # 检查是否为用户令牌
            if not jwt_identity or not isinstance(jwt_identity, str) or not jwt_identity.startswith('user_'):
                return {'code': 401, 'message': '无效的用户认证令牌', 'data': None}, 401
            
            # 提取用户ID
            try:
                user_id = int(jwt_identity.replace('user_', ''))
            except (ValueError, TypeError):
                return {'code': 401, 'message': '令牌中的用户ID格式无效', 'data': None}, 401
            
            # 获取用户信息
            current_user = User.query.get(user_id)
            if not current_user:
                return {'code': 401, 'message': '用户不存在', 'data': None}, 401
            
            if current_user.status not in [1, 2]:  # 正常或待审核状态
                return {'code': 401, 'message': '用户状态异常，无法访问', 'data': None}, 401
            
            # 将current_user注入到kwargs中
            kwargs['current_user'] = current_user
            return f(*args, **kwargs)
            
        except Exception as e:
            # 记录具体错误信息用于调试
            print(f"用户JWT验证错误: {str(e)}")
            error_msg = str(e)
            if 'expired' in error_msg.lower():
                return {'code': 401, 'message': 'Token已过期', 'data': None}, 401
            elif 'invalid' in error_msg.lower():
                return {'code': 401, 'message': 'Token格式无效', 'data': None}, 401
            elif 'signature' in error_msg.lower():
                return {'code': 401, 'message': 'Token签名验证失败', 'data': None}, 401
            else:
                return {'code': 401, 'message': f'认证失败: {error_msg}', 'data': None}, 401
    
    return decorated 